package whu.edu.framework;


import whu.edu.Application;
import whu.edu.bean.InitMethod;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Properties;

public class BootStrapService {

    private final String classPath = "bootstrapClass";



    //加载属性文件
    private static Properties loadProperties(String propFile) throws BootstrapException
    {
        Properties properties = new Properties();
        try(InputStream in = Application.class.getResourceAsStream(propFile))
        {
//            ClassLoader classLoader = BootStrapService.class.getClassLoader();
//            InputStream in = classLoader.getResourceAsStream("myapp.properties");

            if (in == null) {
                System.out.println(in);
                throw new BootstrapException(BootstrapException.ErrorType.FILE_NOTFOUND, "加载属性文件出错，请检查文件是否存在");
            }
            properties.load(in);
            return properties;
        }
        catch (IOException e)
        {
            throw new BootstrapException(BootstrapException.ErrorType.PROP_READ_ERROR, "属性文件读取失败");
        }
    }
    //获取类
    private static Class getClass(Properties properties) throws BootstrapException
    {
        String className = properties.getProperty("bootstrapClass");
        if (className == null) {
            throw new BootstrapException(BootstrapException.ErrorType.PROP_READ_ERROR, "在属性文件中没有设置bootstrapClass");
        }
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw new BootstrapException(BootstrapException.ErrorType.CLASS_NOTFOUND, "属性中标注的类不存在");
        }
    }

    //获取方法
    private static Method getMethod(Class clazz) throws BootstrapException {
        for (Method method : clazz.getDeclaredMethods()) {
            if (!method.isAnnotationPresent(InitMethod.class)) {continue;}
            if (method.getParameterCount() > 0) {
                throw new BootstrapException(BootstrapException.ErrorType.INITMETHOD_ERROR,"带参数的方法不允许标注@InitMethod");
            }
            return method;
        }
        throw new BootstrapException(BootstrapException.ErrorType.INITMETHOD_ERROR,"没有方法标注@InitMethod");
    }

    private static Object creatObject(Class<?> clazz) throws BootstrapException {
        try {
            return clazz.newInstance();
        } catch (InstantiationException e) {
            throw new BootstrapException(BootstrapException.ErrorType.CREATE_OBJECT_ERROR, "创建对象失败，请检查是否有无参构造函数!");
        } catch (IllegalAccessException e) {
            throw new BootstrapException(BootstrapException.ErrorType.CREATE_OBJECT_ERROR, "创建对象失败，类不能是抽象类且无参构造函数不能为私有！");
        }
    }

    private static void invokeMethod(Object obj, Method method) throws BootstrapException {
        try {
            method.setAccessible(true);
            method.invoke(obj);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new BootstrapException(BootstrapException.ErrorType.METHOD_CALL_ERROR, "调用方法失败,请检查方法是否是私有的或者抽象的！");
        }
    }

    public static Object start(String propFile) throws BootstrapException {
        Properties properties = loadProperties(propFile);
        Class clazz = getClass(properties);
        Method method = getMethod(clazz);
        Object obj = Modifier.isStatic(method.getModifiers()) ?
                null : creatObject(clazz);
        invokeMethod(obj, method);
        return obj;
    }
}
